﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Sorteo.BusinessComponents;
using Sorteo.BusinessEntities;

namespace Sorteo.UI
{
    [Flags]
    public enum ToolBarButtons
    {
        None = 0,
        Save = 1,
        Delete = 8,
        New = 16,
        Close = 512
    }

    public partial class PromocionesForm : BaseForm
    {
        #region Declarations

        private int selectedId;
        private TextBox currentTextBox;
        private string oldText;

        // Declaraciones 
        protected const string CloseText = "&Salir";
        protected const string SaveText = "&Guardar";
        protected const string DeleteText = "&Eliminar";
        protected const string NewText = "&Nuevo";

        private const string NamespaceName = "Sorteo.UI";
        private static Stream imageStream;
        private static readonly Assembly assembly = Assembly.GetExecutingAssembly();

        #endregion

        #region Constructors

        public PromocionesForm()
        {
            InitializeComponent();
        }

        #endregion

        #region Event Handlers

        private void PromocionesForm_Load(object sender, EventArgs e)
        {
            ConfigureToolBar(toolStrip, ToolBarButtons.Save |
                                        ToolBarButtons.New |
                                        ToolBarButtons.Delete |
                                        ToolBarButtons.Close);
            ConfigureNumericTextBoxes();
            LoadList();
            New();
        }

        private void promocionesGrid_SelectionChanged(object sender, EventArgs e)
        {
            if (promocionesGrid.SelectedRows.Count > 0)
            {
                var selected = promocionesGrid.SelectedRows[0].DataBoundItem as BEPromocion;
                if (selected != null)
                {
                    selectedId = selected.Id;
                    EnableDisable();
                    UnPack(selected);
                }   
            }
        }

        private void promocionesGrid_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            ConfigurePromocionesGrid();
        }

        private void sorteosGrid_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            currentTextBox = (TextBox)e.Control;
            oldText = currentTextBox.Text;

            currentTextBox.TextChanged -= currentTextBox_TextChanged;
            currentTextBox.TextChanged += currentTextBox_TextChanged;
        }
        
        private void sorteosGrid_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
            CalculaSorteos();
        }

        private void sorteosGrid_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
        {
            CalculaSorteos();
        }

        private void sorteosGrid_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            ConfigureSorteosGrid();
        }

        private void currentTextBox_TextChanged(object sender, EventArgs e)
        {
            if (IsNumeric(currentTextBox.Text))
                oldText = currentTextBox.Text;
            else
                currentTextBox.Text = oldText;
        }

        private void agregarSorteoButton_Click(object sender, EventArgs e)
        {
            var sorteos = sorteosGrid.DataSource as List<BESorteo>;
            if (sorteos != null)
            {
                sorteos.Add(new BESorteo());
                sorteosGrid.DataSource = null;
                sorteosGrid.DataSource = sorteos;
            }
        }

        private void quitarSorteoButton_Click(object sender, EventArgs e)
        {
            var sorteos = sorteosGrid.DataSource as List<BESorteo>;
            if (sorteos != null)
            {
                foreach(DataGridViewRow item in sorteosGrid.SelectedRows)
                {
                    var selected = item.DataBoundItem as BESorteo;
                    if (selected != null)
                        sorteos.Remove(selected);
                }
                sorteosGrid.DataSource = null;
                sorteosGrid.DataSource = sorteos;
            }
        }

        private void toolStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            switch (e.ClickedItem.Text)
            {
                case CloseText:
                    Close();
                    break;

                case SaveText:
                    if (ValidateInput())
                        Save();
                    break;
                
               case NewText:
                    New();
                    break;

               case DeleteText:
                    Delete();
                    break;
            }
        }

        #endregion

        #region Methods: Non-Public

        private void Save()
        {   
            BCPromocion.Save(Pack());
            LoadList();
            New();
        }

        private void New()
        {
            ClearControls(Controls);
            nombreTextBox.Focus();
            selectedId = 0;
            promocionesGrid.ClearSelection();
            sorteosGrid.DataSource = new List<BESorteo>{new BESorteo{Ganadores=1, Orden = 1}};
            EnableDisable();
        }

        private void Delete()
        {
            if (ShowQuestion("¿Está seguro de querer eliminar la promoción seleccionada?"))
            {
                BCPromocion.Delete(selectedId);
                LoadList();
                New();
            }
        }

        private void LoadList()
        {
            promocionesGrid.DataSource = BCPromocion.GetList();
        }

        private bool ValidateInput()
        {
            var name = nombreTextBox.Text.Trim();
            var inicio = inicioDateTime.Value;
            var final = finalDateTime.Value;
            var monto = montoTextBox.Text;
            var acciones = cantidadAccionesTextBox.Text;
            
            decimal dummyDecimal;
            int dummyInt;

            if (string.IsNullOrEmpty(name))
            {
                ShowError("Debe ingresar el nombre");
                nombreTextBox.Focus();
                return false;
            }
            if (inicio > final)
            {
                ShowError("La fecha final debe ser mayor o igual a la fecha de inicio");
                inicioDateTime.Focus();
                return false;
            }
            if (string.IsNullOrEmpty(monto) || !decimal.TryParse(monto, out dummyDecimal))
            {
                ShowError("Debe ingresar el monto");
                montoTextBox.Focus();
                return false;
            }
            if (string.IsNullOrEmpty(acciones) || !int.TryParse(acciones, out dummyInt))
            {
                ShowError("Debe ingresar la cantidad de acciones");
                cantidadAccionesTextBox.Focus();
                return false;
            }
            if (!IsUniqueName(name) && selectedId == 0)
            {
                ShowError("El nombre seleccionado ya ha sido ingresado");
                nombreTextBox.Focus();
                return false;
            }

            if (!IsUniqueName(name) && selectedId == 0)
            {
                ShowError("El nombre seleccionado ya ha sido ingresado");
                nombreTextBox.Focus();
                return false;
            }

            var sorteos = sorteosGrid.DataSource as List<BESorteo>;
            if (sorteos != null)
            {
                if (sorteos.Count == 0)
                {
                    ShowError("Debe ingresar al menos un sorteo");
                    sorteosGrid.Focus();
                    return false;
                }
                foreach(var item in sorteos)
                {
                    if (item.Ganadores == 0)
                    {
                        ShowError("Los sorteos deben tener al menos un ganador");
                        sorteosGrid.Focus();
                        return false;
                    }
                }
            }
            return true;
        }

        private void UnPack(BEPromocion promocion)
        {
            nombreTextBox.Text = promocion.Nombre;
            inicioDateTime.Value = promocion.FechaInicio;
            finalDateTime.Value = promocion.FechaFinal;
            montoTextBox.Text = promocion.Monto.ToString();
            cantidadAccionesTextBox.Text = promocion.CantidadAcciones.ToString();
            favorecerMultiplesVecesCheckBox.Checked = promocion.FavorecerMultiplesVeces;
            sorteosGrid.DataSource = promocion.Sorteos;
        }

        private BEPromocion Pack()
        {
            var promo = new BEPromocion
                            {
                                CantidadAcciones = int.Parse(cantidadAccionesTextBox.Text),
                                FavorecerMultiplesVeces = favorecerMultiplesVecesCheckBox.Checked,
                                FechaFinal = finalDateTime.Value.Date,
                                FechaInicio = inicioDateTime.Value.Date,
                                Monto = decimal.Parse(montoTextBox.Text),
                                Nombre = nombreTextBox.Text,
                                Id = selectedId != 0 ? selectedId : 0
                            };
            foreach(DataGridViewRow item in sorteosGrid.Rows)
                promo.Sorteos.Add((BESorteo)item.DataBoundItem);

            return promo;
        }
        
        private static bool IsNumeric(string input)
        {
            foreach(var c in input.ToCharArray())
                if (!char.IsNumber(c))
                    return false;
            return true;
        }

        private void CalculaSorteos()
        {
            const string ordenColumnName = "Orden";
            for (var i = 0; i < sorteosGrid.Rows.Count; i++)
            {
                if (sorteosGrid.Columns.Contains(ordenColumnName))
                    sorteosGrid.Rows[i].Cells[ordenColumnName].Value = i + 1;//(i + 1).ToString().PadLeft(2, '0');
            }
            
        }

        private void ConfigurePromocionesGrid()
        {
            const string nombreColumnName = "Nombre";
            const string fechaInicioColumnName = "FechaInicio";
            const string fechaFinalColumnName = "FechaFinal";
            var columns = promocionesGrid.Columns;

            var nombreColumn = columns[nombreColumnName];
            var fechaInicioColumn = columns[fechaInicioColumnName];
            var fechaFinalColumn = columns[fechaFinalColumnName];
            if (nombreColumn == null || fechaInicioColumn == null || fechaFinalColumn == null) return;

            foreach (DataGridViewColumn col in columns)
            {
                col.Visible = false;
                col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                col.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
            }
            
            nombreColumn.Visible = true;
            nombreColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
            nombreColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            fechaInicioColumn.Visible = true;
            fechaInicioColumn.DefaultCellStyle.Format = "yyyy-MM-dd";
            fechaInicioColumn.HeaderText = "Inicio";

            fechaFinalColumn.Visible = true;
            fechaFinalColumn.DefaultCellStyle.Format = "yyyy-MM-dd";
            fechaFinalColumn.HeaderText = "Final";
        }

        private void ConfigureSorteosGrid()
        {
            var columns = sorteosGrid.Columns;
            const string ganadoresColumnName = "Ganadores";
            const string ordenColumnName = "Orden";

            var ganadoresColumn = columns[ganadoresColumnName];
            var ordenColumn = columns[ordenColumnName];
            if (ganadoresColumn == null || ordenColumn == null) return;

            foreach (DataGridViewColumn col in columns)
            {
                col.Visible = false;
                col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                col.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
            }
            ordenColumn.Visible = true;
            ordenColumn.DefaultCellStyle.BackColor = Color.LightGray;
            ordenColumn.HeaderText = "Sorteo";
            ordenColumn.DisplayIndex = 0;
            ordenColumn.Width = 45;
            ordenColumn.ReadOnly = true;

            ganadoresColumn.Visible = true;
            ganadoresColumn.HeaderText = "# Ganadores";
            ganadoresColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            ganadoresColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;

            CalculaSorteos();
        }

        private void ConfigureNumericTextBoxes()
        {
            montoTextBox.Format = "#,##0.00";
            cantidadAccionesTextBox.Format = "#,##0";
        }

        private static void ConfigureToolBar(ToolStrip toolStrip, ToolBarButtons buttons)
        {
            toolStrip.Items.Clear();

            if (ContainsButton(buttons, ToolBarButtons.New))
                AddToolStripButton(toolStrip, ToolBarButtons.New);

            if (ContainsButton(buttons, ToolBarButtons.Save))
                AddToolStripButton(toolStrip, ToolBarButtons.Save);
            
            if (ContainsButton(buttons, ToolBarButtons.Delete))
                AddToolStripButton(toolStrip, ToolBarButtons.Delete);

            if (toolStrip.Items.Count > 0 && toolStrip.Items[toolStrip.Items.Count - 1].CanSelect)
                AddToolStripSeparator(toolStrip);

            AddToolStripButton(toolStrip, ToolBarButtons.Close);
        }

        private static bool ContainsButton(ToolBarButtons combined, ToolBarButtons checkagainst)
        {
            return ((combined & checkagainst) == checkagainst);
        }

        private static void AddToolStripButton(ToolStrip toolStrip, ToolBarButtons buttonType)
        {
            var newButton = new ToolStripButton();
            string imageName = "", text = "";

            switch (buttonType)
            {
                case ToolBarButtons.Save:
                    {
                        text = SaveText;
                        imageName = NamespaceName + ".Images.tb_save.png";
                        break;
                    }
                case ToolBarButtons.Delete:
                    {
                        text = DeleteText;
                        imageName = NamespaceName + ".Images.tb_delete.png";
                        break;
                    }
                case ToolBarButtons.New:
                    {
                        text = NewText;
                        imageName = NamespaceName + ".Images.tb_add.png";
                        break;
                    }
                case ToolBarButtons.Close:
                    {
                        text = CloseText;
                        imageName = NamespaceName + ".Images.tb_close.png";
                        break;
                    }
            }

            // Lee imagen de los resources del assembly
            imageStream = assembly.GetManifestResourceStream(imageName);
            newButton.Text = text;
            newButton.Name = text;
            if (imageStream != null)
                newButton.Image = Image.FromStream(imageStream);
            newButton.TextAlign = ContentAlignment.BottomCenter;
            newButton.TextImageRelation = TextImageRelation.ImageAboveText;
            newButton.ImageScaling = ToolStripItemImageScaling.SizeToFit;
            newButton.AutoSize = true;
            newButton.Tag = buttonType;

            toolStrip.Items.Add(newButton);
        }

        private static void AddToolStripSeparator(ToolStrip toolStrip)
        {
            var separator = new ToolStripSeparator {Tag = ToolBarButtons.None};
            toolStrip.Items.Add(separator);
        }

        protected static bool IsUniqueName(string name)
        {
            var list = BCPromocion.GetList();
            var matches = (from p in list where p.Nombre == name select p).Count();
            return (matches == 0);
        }
        
        private void EnableDisable()
        {
            toolStrip.Items[DeleteText].Enabled = promocionesGrid.SelectedRows.Count > 0;
        }

        #endregion
    }
}